﻿using Windows.UI.Xaml;

namespace Uhimania.Libraries.Windows.Interactivity
{
    #region Interaction
    /// <summary>
    /// プロパティにアタッチされた <see cref="TriggerBase"/> および
    /// <see cref="Behavior"/> を所有する静的クラス。
    /// </summary>
    public static class Interaction
    {
        #region Behaviors

        /// <summary>
        /// Behaviors を識別する依存関係プロパティ。
        /// </summary>
        private static readonly DependencyProperty BehaviorsProperty =
            DependencyProperty.RegisterAttached(
                "Behaviors",
                typeof(BehaviorCollection),
                typeof(Interaction),
                new PropertyMetadata(null, OnBehaviorsChanged)
            );

        /// <summary>
        /// 指定したオブジェクトに関連付けられた <see cref="Behavior"/> を含む
        /// <see cref="BehaviorCollection"/> を取得する。
        /// </summary>
        /// <param name="obj"><see cref="BehaviorCollection"/> の取得元オブジェクト。</param>
        /// <returns>指定したオブジェクトに関連付けられた <see cref="Behavior"/> を含む <see cref="BehaviorCollection"/>。</returns>
        public static BehaviorCollection GetBehaviors(DependencyObject obj)
        {
            var list = obj.GetValue(BehaviorsProperty) as BehaviorCollection;
            if (list == null)
            {
                list = new BehaviorCollection();
                obj.SetValue(BehaviorsProperty, list);
            }

            return list;
        }

        /// <summary>
        /// Behaviors が変更されたときに呼び出される。
        /// </summary>
        /// <param name="obj">イベントソース。</param>
        /// <param name="e">イベントデータ。</param>
        private static void OnBehaviorsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var oldList = e.OldValue as BehaviorCollection;
            var newList = e.NewValue as BehaviorCollection;

            if (oldList != newList)
            {
                if (oldList != null && oldList.AssociatedObject != null)
                    oldList.Detach();

                if (newList != null && obj != null)
                    newList.Attach(obj);
            }
        }

        #endregion

        #region Triggers

        /// <summary>
        /// Triggers を識別する依存関係プロパティ。
        /// </summary>
        private static readonly DependencyProperty TriggersProperty =
            DependencyProperty.RegisterAttached(
                "Triggers",
                typeof(TriggerCollection),
                typeof(Interaction),
                new PropertyMetadata(null, OnTriggersChanged)
            );

        /// <summary>
        /// 指定したオブジェクトに関連付けられた <see cref="TriggerBase"/> を含む
        /// <see cref="TriggerCollection"/> を取得する。
        /// </summary>
        /// <param name="obj"><see cref="TriggerCollection"/> の取得元オブジェクト。</param>
        /// <returns>指定したオブジェクトに関連付けられた <see cref="TriggerBase"/> を含む <see cref="TriggerCollection"/>。</returns>
        public static TriggerCollection GetTriggers(DependencyObject obj)
        {
            var list = obj.GetValue(TriggersProperty) as TriggerCollection;
            if (list == null)
            {
                list = new TriggerCollection();
                obj.SetValue(TriggersProperty, list);
            }

            return list;
        }

        /// <summary>
        /// Triggers が変更されたときに呼び出される。
        /// </summary>
        /// <param name="obj">イベントソース。</param>
        /// <param name="e">イベントデータ。</param>
        private static void OnTriggersChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var oldList = e.OldValue as TriggerCollection;
            var newList = e.NewValue as TriggerCollection;

            if (oldList != newList)
            {
                if (oldList != null && oldList.AssociatedObject != null)
                    oldList.Detach();

                if (newList != null && obj != null)
                    newList.Attach(obj);
            }
        }

        #endregion
    }
    #endregion
}
